﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Funq.Tests
{
    [TestClass]
    public class ContainerBuilderFixture
    {
        [TestMethod]
        public void AllowsRegistrationOfTypes()
        {
            var builder = new ContainerBuilder();
            Func<Container, IBar> factory1 = c => new Bar();
            Func<Container, string, bool, IBar> factory2 = (c, s, b) => new Bar(s, b);
            Func<Container, IFoo> factory3 = c => new Foo(c.Resolve<IBar>());

            var registration1 = builder.Register<IBar>(factory1);
            var registration2 = builder.Register<IBar, string, bool>(factory2);
            var registration3 = builder.Register<IFoo>(factory3);

            var key1 = new ContainerKey(typeof(IBar), factory1.GetType());
            var key2 = new ContainerKey(typeof(IBar), factory2.GetType());
            var key3 = new ContainerKey(typeof(IFoo), factory3.GetType());

            Assert.AreEqual(key1, registration1.Key);
            Assert.AreEqual(factory1, registration1.Entry.Factory);

            Assert.AreEqual(key2, registration2.Key);
            Assert.AreEqual(factory2, registration2.Entry.Factory);

            Assert.AreEqual(key3, registration3.Key);
            Assert.AreEqual(factory3, registration3.Entry.Factory);
        }

        [TestMethod]
        public void AllowsNamingRegistrations()
        {
            var builder = new ContainerBuilder();
            Func<Container, IBar> factory1 = c => new Bar();
            var registration1 = builder.Register<IBar>(factory1);

            registration1.Named("A");

            var key1 = new ContainerKey(typeof(IBar), factory1.GetType()) { Name = "A" };
            Assert.AreEqual(key1, registration1.Key);
            Assert.AreEqual(key1.Name, registration1.Key.Name);
            Assert.AreEqual(factory1, registration1.Entry.Factory);
        }

        [TestMethod]
        public void BuildCreatesTheContainerWithAllRegistrations()
        {
            var builder = new ContainerBuilder();
            Func<Container, IBar> factory = c => new Bar();
            Func<Container, IBar> factory1 = c => new Bar();
            Func<Container, string, bool, IBar> factory2 = (c, s, b) => new Bar(s, b);
            Func<Container, IFoo> factory3 = c => new Foo(c.Resolve<IBar>());

            const string STR_NAME = "A";
            var registration = builder.Register<IBar>(factory);
            registration.Named(STR_NAME);
            var registration1 = builder.Register<IBar>(factory1);
            var registration2 = builder.Register<IBar, string, bool>(factory2);
            var registration3 = builder.Register<IFoo>(factory3);

            var container = builder.Build();
            Assert.IsNotNull(container.ResolveNamed<IBar>(STR_NAME));
            Assert.IsNotNull(container.Resolve<IBar>());
            Assert.IsNotNull(container.Resolve<IBar, string, bool>("ABC", true));
            Assert.IsNotNull(container.Resolve<IFoo>());
        }
    }
}
